package com.goldsprite.infinityworld.screens.examples.entity;

import com.badlogic.gdx.graphics.*;
import com.badlogic.gdx.graphics.g2d.*;
import com.badlogic.gdx.scenes.scene2d.ui.*;
import com.badlogic.gdx.utils.viewport.*;
import com.goldsprite.gdxcore.entities.*;
import java.util.*;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.utils.Array;
import com.goldsprite.gdxcore.logs.LogViewerService;
import com.goldsprite.gdxcore.screens.GScreen;
import com.goldsprite.gdxcore.ui.GSplitPane;
import com.goldsprite.gdxcore.utils.OrthoCamController;
import com.goldsprite.gdxcore.utils.sorts.EntitySort;
import com.goldsprite.infinityworld.assets.GlobalAssets;
import com.goldsprite.infinityworld.entities.components.RockerRoleController;
import com.goldsprite.infinityworld.entities.randommap.BlockId;
import com.goldsprite.simplexnoise.SimplexNoise2D;
import com.goldsprite.utils.math.Vector2;

public class CustomSortRendererExampleScreen extends GScreen{
	//世界参数
	private float worldWidth = 1060, worldHeight = 540;
	private Viewport viewport;
	private OrthographicCamera worldCam, uiCam;
	
	//实体渲染
	private SpriteBatch batch;
	//debug绘制
	private ShapeRenderer gizmos;
	//ui触控渲染
	private Skin skin;
	private Touchpad rocker;
	private Stage stage;

	//实体组
	private EntitySort<TmpBlock> entSorter;
	private Array<TmpBlock> objects = new Array<>();
	private AnimatorEntity role;
	private TmpBlock playerRect;
	private TmpBlock tmpBlock;
	private Array<TmpBlock> ground = new Array<>();

	//功能组件
	private RockerRoleController roleCtrl;
	private OrthoCamController worldCamCtrl;

	@Override
	public Viewport getViewport() {
		return viewport;
	}


	@Override
	public void create() {
		uiCam = new OrthographicCamera();
		viewport = new FitViewport(worldWidth, worldHeight, uiCam);
		viewport.apply(true);

		worldCam = new OrthographicCamera();
		worldCam.viewportWidth = uiCam.viewportWidth;
		worldCam.viewportHeight = uiCam.viewportHeight;
		worldCam.position.set(uiCam.position);

		batch = new SpriteBatch();
		gizmos = new ShapeRenderer();
		
		skin = GlobalAssets.getInstance().editorSkin;

		stage = new Stage(viewport);
		getImp().addProcessor(stage);

		//日志布局
		LogViewerService logViewer = new LogViewerService(skin);
		Table emptyTable = new Table();
		GSplitPane consoleSplit = new GSplitPane(emptyTable, logViewer.getRootLayout(), false, skin);
		consoleSplit.setAbsoluteSplitAmount(1f);
		consoleSplit.setFillParent(true);
		stage.addActor(consoleSplit);

		//排序器
		entSorter = new EntitySort<TmpBlock>(objects, false);

		//生成材质
		Texture tiles = new Texture(Gdx.files.internal(BlockId.cellTexturesPath));
		TextureRegion[][] splitTiles = TextureRegion.split(tiles, BlockId.regionSplit, BlockId.regionSplit);
		int gridCountX = tiles.getWidth()/BlockId.regionSplit;
		int gridCountY = tiles.getHeight()/BlockId.regionSplit;
		//随机生成元素
		float scl = 0.4f, xRange = 100*scl, yRange = 100*scl;
		float blockRenderSize = 64;
		//生成有序随机地图
		int startX = 530, startY = 575;
		int mapWidth = 50, mapHeight = 50;
		for(int l=0;l<2;l++){
			for(int y=mapHeight-1;y>=0;y--){
				for(int x=0;x<mapWidth;x++){
					BlockId blockId = getRanBlock(startX+x, startY+y, l);
					TextureRegion region = splitTiles[blockId.y][blockId.x];
					if(blockId.equals(BlockId.Air)) continue;
					TmpBlock block = newBlock(region, x*blockRenderSize, y*blockRenderSize, blockRenderSize, l==1);
					block.setSorter(entSorter);
					if(l==0) ground.add(block);
				}
			}
		}
		//生成随机方块列表
		for(int i=0;i<100;i++){
			//随机参数
			double ran = new Random().nextDouble();
			int ranIndexX = (int)(ran*gridCountX);
			double ran2 = new Random().nextDouble();
			int ranIndexY = (int)(ran2*gridCountY);
			TextureRegion region = splitTiles[ranIndexY][ranIndexX];
			//填充数据
			TmpBlock block = newBlock(
				region, 
				(int)(new Random().nextInt((int)xRange)*blockRenderSize), 
				(int)(new Random().nextInt((int)yRange)*blockRenderSize), 
				64, true
			);
			block.setSorter(entSorter);
		}
		//tmpBlock = newBlock(splitTiles[3][2], 300, 200, 64, true);
		//tmpBlock.setSorter(entSorter);
		

		//玩家
		createPlayer();
		playerRect = new TmpBlock(){
			public float z(){
				//return pos.y - role.getBodySize().y;
				float downY = originPos.y - renderSize.y/2;
				float footPivotOffset = role.getFootPivotOffset().y;
				return downY+footPivotOffset;
			}
		};
		playerRect.setSorter(entSorter);
		playerRect.renderSize.set(role.getSize());
		objects.add(playerRect);

		//ui部分

		//触控ui部分
		//摇杆
		float size = 150, margin = 20;
		rocker = new Touchpad(0, skin);
		rocker.setBounds(margin, margin, size, size);
		stage.addActor(rocker);

		//摇杆移动组件
		roleCtrl = new RockerRoleController(role, rocker);
		roleCtrl.roleMoveVel = 180;
		boolean[] isUIEvent = {false};
		//地图相机控制组件
		worldCamCtrl = new OrthoCamController(worldCam, isUIEvent);
		getImp().addProcessor(worldCamCtrl);
	}

	private void createPlayer(){
		String roleTexPath = "roles/Soldier.png";
		Texture roleTex = new Texture(Gdx.files.internal(roleTexPath));

		//统一动画速度
		float animPerVel = 1;
		// 创建动画器并导入源材质与设置帧单位大小
		role = new AnimatorEntity(roleTex, 100, 100);
		role.bodyBound.set(15, 18);
		role.footPivot.set(50, 43);
		//设置动画
		role.addAnimation("Idle", 0, 6, animPerVel / 6);
		role.addAnimation("Walk", 1, 8, animPerVel / 8);
		role.setCurAnimation("Idle");
		//设置实体大小
		role.setScl(4f);
		Vector2 startPos = new Vector2(200, 200);
		role.setCenterPosition(startPos.x+role.getBodySize().x/2, startPos.y+role.getBodySize().y/2);
	}

	private TmpBlock newBlock(TextureRegion region, float x, float y, float renderSize, boolean join) {
		TmpBlock block = new TmpBlock();
		block.region = region;
		block.originPos.x = x;
		block.originPos.y = y;
		block.renderSize.set(renderSize);
		if(join) objects.add(block);
		return block;
	}


	@Override
	public void render(float delta) {
		super.render(delta);

		updateEnts(delta);
		Gdx.gl.glViewport(300, 0, (int)(worldWidth*2), (int)(worldHeight*2));
		renderEnts(delta);
		viewport.apply(true);

		batch.setProjectionMatrix(uiCam.combined);
		stage.act(delta);
		stage.draw();
	}

	private void updateEnts(float delta) {
		//角色控制
		roleCtrl.update(delta);
		//逻辑更新：动画
		role.act(delta);
		//同步数据：动画帧，位置
		playerRect.region = role.getCurFrame();
		playerRect.originPos.set(role.getCenterPosition());

		//排序器
		if(playerRect.isSort()){
			//int oldIndex = entSorter.indexOf(playerRect);
			entSorter.sort();
			//LogViewerService.logDebug("玩家触发排序：旧序数: %d, 新序数: %d", oldIndex, entSorter.indexOf(playerRect));
			//LogViewerService.logDebug("玩家rect位置: %s, z: %.2f    tmpBlock位置: %s, z: %.2f", playerRect.pos, playerRect.z(), tmpBlock.pos, tmpBlock.z());
		}

		//相机绑定玩家
		//worldCam.position.set(playerRect.pos.x+worldCam.viewportWidth/2-150, playerRect.pos.y+worldCam.viewportHeight/2, 0);
	}

	private void renderEnts(float delta) {
		worldCam.update();
		batch.setProjectionMatrix(worldCam.combined);

		batch.begin();
		float leftDownX = 0, leftDownY=0;
		//地面
		for(TmpBlock block : ground){
			leftDownX = block.originPos.x-block.renderSize.x/2;
			leftDownY = block.originPos.y-block.renderSize.y/2;
			batch.draw(block.region, leftDownX, leftDownY, block.renderSize.x, block.renderSize.y);
		}
		//物体
		for(TmpBlock obj : objects){
			leftDownX = obj.originPos.x-obj.renderSize.x/2;
			leftDownY = obj.originPos.y-obj.renderSize.y/2;
			batch.draw(obj.region, leftDownX, leftDownY, obj.renderSize.x, obj.renderSize.y);
		}
		batch.end();
		
		//drawDebug
		gizmos.setProjectionMatrix(worldCam.combined);
		Gdx.gl.glLineWidth(2);
		gizmos.begin(ShapeRenderer.ShapeType.Line);
		float gizmoSize = 10, cx, cy;
		for(TmpBlock obj : objects){
			cx = obj.originPos.x;
			cy = obj.originPos.y;
			leftDownX = cx-obj.renderSize.x/2;
			leftDownY = cy-obj.renderSize.y/2;
			//bound
			gizmos.rect(leftDownX, leftDownY, obj.renderSize.x, obj.renderSize.y);
			//leftDown
			//gizmos.circle(leftDownX, leftDownY, gizmoSize);
			//center
			//gizmos.circle(cx, cy, gizmoSize);
			//zPoint
			gizmos.circle(cx, obj.z(), gizmoSize);
		}
		gizmos.end();
	}
	

	private int minHigh = -64, maxHigh = 64;
	private BlockId getRanBlock(int x, int y, int type){
		double noise = SimplexNoise2D.getNorNoise(x, y, 0.02, 5, 0.45);
		double height = mapNoiseToHeight(noise, minHigh, maxHigh);
		BlockId blockId = getBlockIdForHeight(height);

		//生成obj(树等)
		BlockId objId = BlockId.Air;
		//ran决定出现树的覆盖率
		float ran = new Random((long)(noise*1_000_000)).nextFloat();
		//草地树
		if(height>40+off){
			if(ran > 0.5f){
				if(ran < 0.65f) objId = BlockId.Tree;
				else objId = BlockId.Tree2;
			}
		}
		//沙滩树
		if(height>28+off+1 && height<34+off){
			if(ran > 0.8f)objId = BlockId.BeachTree;
		}

		return type == 0 ?blockId :objId;
	}

	////旧版代码
	public int off = -22;//越小目标高度面积越大
    // 高度映射表：每个高度范围对应一个BlockId
    public TreeMap<Integer, BlockId> heightMap = new TreeMap<Integer, BlockId>(){{
			//put(64+off, BlockId.Air);
			put(40+off, BlockId.Grass);
			put(38+off, BlockId.Grass2);
			put(34+off, BlockId.Sand);
			put(28+off, BlockId.Water);
			put(24+off, BlockId.Water2);
			put(18+off, BlockId.Water3);
			put(10+off, BlockId.Water4);
		}};
    public TreeMap<Integer, BlockId> obj_heightMap = new TreeMap<Integer, BlockId>(){{
			//put(64+off, BlockId.Air);
			put(45+off, BlockId.Tree);
			put(40+off, BlockId.Air);
		}};

	// 将噪声值映射到指定的高度区间, 接收值区间: 0 ~ 1
    private double mapNoiseToHeight(double noiseValue, int minHeight, int maxHeight) {
        return minHeight + noiseValue * (maxHeight - minHeight);
    }

    // 根据高度值查找对应的BlockId
    private BlockId getBlockIdForHeight(double height) {
		Integer key = heightMap.ceilingKey((int) height);  // 向上对齐到最近的高度
		if (key == null) key = heightMap.lastKey();
		return heightMap.get(key);
	}

}
